package com.example.demo.API;

/**
 * Created with IntelliJ IEDA.
 * Description:
 * User:86186
 * Date:2023-10-25
 * Time:22:21
 */

import com.example.demo.common.AppVariable;
import com.example.demo.entity.Userinfo;
import com.example.demo.request.MatchRequest;
import com.example.demo.response.MatchResponse;
import com.example.demo.game.Matcher;
import com.example.demo.game.OnlineUserManager;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

/**
 * 通过这个类来处理 匹配中的 websocket 请求
 */
@Component
public class MatchController extends TextWebSocketHandler {
    private ObjectMapper objectMapper = new ObjectMapper();

    @Autowired
    private OnlineUserManager onlineUserManager;

    @Autowired
    private Matcher matcher;



    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        //玩家上线，加入到 onlineUserManager 中

        // 1.获取到当前用户的消息（谁在游戏大厅，建立的连接）
        //  此处的代码，之所以能够 getAttributes ，全靠了在注册 websocket 的时候
        //  加上的.addInterceptors(new HttpSessionHandshakeInterceptor());
        //  这个逻辑就把 HttpSession 中的 Attribute 都给拿到 websocketSession 中了
        //  在 Http 逻辑中，王 HttpSession 中存了 UserInfo 数据： session.setAttribute(AppVariable.USER_SESSION_KEY,userinfo);
        //  此处就可以在 WebSOcketSession 中把之前 HttpSession 中存的 Userinfo 对象给拿到了
       try {
           Userinfo userinfo = (Userinfo) session.getAttributes().get(AppVariable.USER_SESSION_KEY);

           // 2.先判定当前用户是否是已经在线状态，如果已经在线，就不该继续进行后续操作
           if (onlineUserManager.getFromGameRoom(userinfo.getId()) != null ||
                   onlineUserManager.getFromGameHall(userinfo.getId()) != null){
               //当前用户已经登录了
               //针对这个情况，要告知客户端，这里重复登录了
               MatchResponse response = new MatchResponse();
               response.setOk(true);
               response.setResaon("当前禁止多开!");
               response.setMessage("repeatConnection");
               System.out.println("触发多开!!");
               session.sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));
               //session.close();

               return;
           }

           // 3.拿到身份信息之后就可以把玩家设置为在线状态了
           onlineUserManager.enterGameHall(userinfo.getId(),session);
           System.out.println("玩家" + userinfo.getUsername() + "进入游戏大厅 !");
       }catch (NullPointerException e){
           System.out.println("[MatchController.afterConnectionEstablished]当前用户未登录");
           //e.printStackTrace();
           //出现空指针异常，说明当前用户的身份信息为空，用户还未登录呢
           //把当前用户尚未登录的信息返回回去
           MatchResponse response = new MatchResponse();
           response.setOk(false);
           response.setResaon("您尚未登录，不能进行后续匹配功能！");
           //先通过 ObjectMapper 把 MatchResponse 对象转成 JSON 字符串
           //然后再包装上一层 TextMessage 再进行传输
           //TextMessage 就表示一个文本格式的 websocket 数据包
           session.sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));
       }
    }

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        // 实现处理开始匹配请求和处理停止匹配请求
        Userinfo userinfo = (Userinfo) session.getAttributes().get(AppVariable.USER_SESSION_KEY);
        // 获取到客户端给服务器发送的数据
        String payload = message.getPayload();
        // 当前这个数据载荷是一个 JSON 格式的字符串，就需要转成 Java 对象
        MatchRequest request = objectMapper.readValue(payload, MatchRequest.class);
        // 从客户端读来的数据
        MatchResponse response = new MatchResponse();
        if (request.getMessage().equals("startMatch")){
            // 进入匹配队列
            matcher.add(userinfo);
            response.setOk(true);
            response.setMessage("startMatch");
        }else if (request.getMessage().equals("stopMatch")){
            // 退出匹配队列
            matcher.remove(userinfo);
            response.setOk(true);
            response.setMessage("stopMatch");
        }else {
            // 非法情况
            response.setOk(false);
            response.setMessage("非法的匹配请求");
        }
        String json = objectMapper.writeValueAsString(response);
        session.sendMessage(new TextMessage(json));
    }

    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        //玩家下线，从 onlineUserManager 中删除
        try {
            Userinfo userinfo = (Userinfo) session.getAttributes().get(AppVariable.USER_SESSION_KEY);
            WebSocketSession tmpSessoon = onlineUserManager.getFromGameHall(userinfo.getId());
            if (tmpSessoon == session){
                onlineUserManager.exitGameHall(userinfo.getId());
            }
            // 玩家正在匹配中突然连接断裂
            matcher.remove(userinfo);
        }catch (NullPointerException e){
            System.out.println("[MatchController.handleTransportError]当前用户未登录");
            //e.printStackTrace();
            //出现空指针异常，说明当前用户的身份信息为空，用户还未登录呢
            //把当前用户尚未登录的信息返回回去
//            MatchResponse response = new MatchResponse();
//            response.setOk(false);
//            response.setResaon("您尚未登录，不能进行后续匹配功能！");
//            //先通过 ObjectMapper 把 MatchResponse 对象转成 JSON 字符串
//            //然后再包装上一层 TextMessage 再进行传输
//            //TextMessage 就表示一个文本格式的 websocket 数据包
//            session.sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));
        }
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        //玩家下线，从 onlineUserManager 中删除
        try {
            Userinfo userinfo = (Userinfo) session.getAttributes().get(AppVariable.USER_SESSION_KEY);
            WebSocketSession tmpSessoon = onlineUserManager.getFromGameHall(userinfo.getId());
            if (tmpSessoon == session){
                onlineUserManager.exitGameHall(userinfo.getId());
            }
            matcher.remove(userinfo);
        }catch (NullPointerException e){
            System.out.println("[MatchController.afterConnectionClosed]当前用户未登录");
            //e.printStackTrace();
            //出现空指针异常，说明当前用户的身份信息为空，用户还未登录呢
            //把当前用户尚未登录的信息返回回去
//            MatchResponse response = new MatchResponse();
//            response.setOk(false);
//            response.setResaon("您尚未登录，不能进行后续匹配功能！");
            //先通过 ObjectMapper 把 MatchResponse 对象转成 JSON 字符串
            //然后再包装上一层 TextMessage 再进行传输
            //TextMessage 就表示一个文本格式的 websocket 数据包
            //session.sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));
        }
    }
}
